home *** CD-ROM | disk | FTP | other *** search
/ Sprite 1984 - 1993 / Sprite 1984 - 1993.iso / src / boot / netBoot.new / dev / sc.c < prev    next >
C/C++ Source or Header  |  1990-12-19  |  6KB  |  268 lines

  1.  
  2. #ifndef lint
  3. /* static    char sccsid[] = "@(#)sc.c 1.1 86/09/27 Copyr 1986 Sun Micro"; */
  4. #endif
  5.  
  6. /*
  7.  * Copyright (c) 1986 by Sun Microsystems, Inc.
  8.  */
  9.  
  10. #include "../h/types.h"
  11. #include "../h/buf.h"
  12. #include "../dev/screg.h"
  13. #include "../dev/sireg.h"
  14. #include "../dev/scsi.h"
  15. #include "../dev/saio.h"
  16. #include "../h/sunromvec.h"
  17. #include "../h/idprom.h"
  18.  
  19. /*
  20.  * Low-level routines common to all devices on the SCSI bus
  21.  */
  22.  
  23. /*
  24.  * Interface to the routines in this module is via a second "sip"
  25.  * structure contained in the caller's local variables.
  26.  *
  27.  * This "sip" must be initialized with sip->si_boottab = scdriver
  28.  * and must then be devopen()ed before any I/O can be done.
  29.  *
  30.  * The device must be closed with devclose().
  31.  */
  32.  
  33. /* How our addrs look to the SCSI DMA hardware */
  34. #define    SCSI_DMA_ADDR(x)    (((int)x)&0x000FFFFF)
  35.  
  36. /*
  37.  * The interfaces we export
  38.  */
  39. extern int nullsys();
  40. int scopen();
  41.  
  42. struct boottab scdriver =
  43.     {"sd",    nullsys,    nullsys,    scopen,        nullsys,
  44.         nullsys,    "",    0};
  45.  
  46. char seqerr_msg[] = "sequence error";    /* Saves dup copy of string */
  47.  
  48. /*
  49.  * Record an error message from scsi
  50.  */
  51. sc_error(msg)
  52.     char *msg;
  53. {
  54.     printf("scsi: %s\n", msg);
  55. }
  56.  
  57. #define    SCSI_MULTI_BASE    0x80000
  58. #define    SCSI_VME_BASE    0x200000
  59. #define    SCSI_SIZE    0x4000        /* incr to next board - OK for VME ? */
  60. #define    SCSI_NSTD    2        /* # of standard address boards */
  61.  
  62. /*
  63.  * Open the SCSI host adapter.
  64.  * Note that the Multibus address and the VME address
  65.  * are totally different, although both are controller '0'.
  66.  * More fon goes here for the model 25.
  67.  */
  68. int
  69. scopen(sip)
  70.     register struct saioreq    *sip;
  71. {
  72.     register struct scsi_ha_reg *har;
  73.     struct idprom id;
  74.     register int base;
  75.     enum MAPTYPES space;
  76.     char *devalloc();
  77.  
  78.     if (idprom(IDFORM_1, &id) == IDFORM_1 &&
  79.         id.id_machine == IDM_SUN2_MULTI) {
  80.         base = SCSI_MULTI_BASE;
  81.         space = MAP_MBMEM;
  82.     } else {
  83.         base = SCSI_VME_BASE;
  84.         space = MAP_VME24A16D;
  85.     }
  86.     if (sip->si_ctlr < SCSI_NSTD)
  87.         sip->si_ctlr = base + sip->si_ctlr * SCSI_SIZE;
  88.     /* now map it in */
  89.     sip->si_devaddr = devalloc(space, sip->si_ctlr,
  90.         sizeof (struct scsi_ha_reg));
  91.     if (sip->si_devaddr == 0)
  92.         return (-1);
  93.  
  94.     har = (struct scsi_ha_reg *) sip->si_devaddr;
  95.     har->icr = 0;
  96.     return 0;
  97. }
  98.  
  99.  
  100. /*
  101.  * Write a command to the SCSI bus.
  102.  *
  103.  * The supplied sip is the one opened by scopen().
  104.  * DMA is done based on sip->si_ma and sip->si_cc.
  105.  *
  106.  * Returns -1 for error, otherwise returns the residual count not DMAed
  107.  * (zero for success).
  108.  *
  109.  * FIXME, this must be accessed via a boottab vector,
  110.  * to allow host adap to switch.
  111.  * Must pass cdb, scb in sip somewhere...
  112.  */
  113. int
  114. scdoit(cdb, scb, sip)
  115.     register struct scsi_cdb *cdb;
  116.     register struct scsi_scb *scb;
  117.     register struct saioreq *sip;
  118. {
  119.     register char *cp;
  120.     register int i, b;
  121.     register struct scsi_ha_reg *har;
  122.  
  123.     har = (struct scsi_ha_reg *) sip->si_devaddr;
  124.  
  125.     /* select controller */
  126.     har->data = 1 << sip->si_unit;        /* Set target on SCSI bus */
  127.  
  128.     i = 100000;
  129.     for(;;) {
  130.         if ((har->icr & ICR_BUSY) == 0) {
  131.             break;
  132.         }
  133.         if (i-- <= 0) {
  134.             sc_error("bus continuously busy");
  135.             har->icr = ICR_RESET;
  136.             DELAY(50);
  137.             har->icr = 0;
  138.             return (-1);
  139.         }
  140.     }
  141.     har->icr = ICR_SELECT;
  142.     if (sc_wait(har, ICR_BUSY) == 0) {
  143.         /*
  144.          * No response to select.  Reset bus and get out.
  145.          */
  146.         sc_error("no such controller on SCSI bus");
  147.         har->icr = ICR_RESET;
  148.         DELAY(50);
  149.         har->icr = 0;
  150.         return (-1);
  151.     }
  152.     /* pass command */
  153.     har->icr = ICR_WORD_MODE | ICR_DMA_ENABLE;
  154.     har->dma_addr = SCSI_DMA_ADDR(sip->si_ma);
  155.     har->dma_count = ~sip->si_cc;
  156.     cp = (char *) cdb;
  157.     for (i = 0; i < sizeof (struct scsi_cdb); i++) {
  158.         if (sc_putbyte(har, ICR_COMMAND, *cp++) == 0) {
  159.             return (-1);
  160.         }
  161.     }
  162.     /* wait for command completion */
  163.     if (sc_wait(har, ICR_INTERRUPT_REQUEST) == 0) {
  164.         return (-1);
  165.     }
  166.     /* handle odd length dma transfer, adjust dma count */
  167.     if (har->icr & ICR_ODD_LENGTH) {
  168.         if ((cdb->cmd == SC_REQUEST_SENSE) || (cdb->cmd == SC_READ)) {
  169.                 cp = (char *)sip->si_ma + sip->si_cc - 1;
  170.                 *cp = (char)har->data;
  171.             har->dma_count = ~(~har->dma_count - 1);
  172.         } else {
  173.             har->dma_count = ~(~har->dma_count + 1);
  174.         }
  175.     }
  176.     /* get status */
  177.     cp = (char *) scb;
  178.     i = 0;
  179.     for (;;) {
  180.         b = sc_getbyte(har, ICR_STATUS);
  181.         if (b == -1) {
  182.             break;
  183.         }
  184.         if (i < STATUS_LEN) {
  185.             cp[i++] = b;
  186.         }
  187.     }
  188.     b = sc_getbyte(har, ICR_MESSAGE_IN);
  189.     if (b != SC_COMMAND_COMPLETE) {
  190.         if (b >= 0) {    /* if not, sc_getbyte already printed msg */
  191.             sc_error("invalid message");
  192.         }
  193.         return (-1);
  194.     }
  195.     return (sip->si_cc - ~har->dma_count);
  196. }
  197.  
  198.  
  199. /*
  200.  * Wait for a condition on the scsi bus.
  201.  */
  202. int
  203. sc_wait(har, cond)
  204.     register struct scsi_ha_reg *har;
  205. {
  206.     register int icr, count;
  207.  
  208.     if (cond == ICR_INTERRUPT_REQUEST) {
  209.         count = 1000000;
  210.     } else {
  211.         count = 10000;
  212.     }
  213.     while (((icr = har->icr) & cond) != cond) {
  214.         if (--count <= 0) {
  215.             sc_error("timeout");
  216.             return (0);
  217.         }
  218.         if (icr & ICR_BUS_ERROR) {
  219.             sc_error("bus error");
  220.             return (0);
  221.         }
  222.         DELAY(5000);
  223.     }
  224.     return (1);
  225. }
  226.  
  227.  
  228. /*
  229.  * Put a byte into the scsi command register.
  230.  */
  231. int
  232. sc_putbyte(har, bits, c)
  233.     register struct scsi_ha_reg *har;
  234. {
  235.     if (sc_wait(har, ICR_REQUEST) == 0) {
  236.         return (0);
  237.     }
  238.     if ((har->icr & ICR_BITS) != bits) {
  239.         sc_error(seqerr_msg);
  240.         return (0);
  241.     }
  242.     har->cmd_stat = c;
  243.     return (1);
  244. }
  245.  
  246.  
  247. /*
  248.  * Get a byte from the scsi command/status register.
  249.  * <bits> defines the bits we want to see on in the ICR.
  250.  * If <bits> is wrong, we print a message -- unless <bits> is ICR_STATUS.
  251.  * This hack is because scdoit keeps calling getbyte until it sees a non-
  252.  * status byte; this is not an error in sequence as long as the next byte
  253.  * has MESSAGE_IN tags.  FIXME.
  254.  */
  255. int
  256. sc_getbyte(har, bits)
  257.     register struct scsi_ha_reg *har;
  258. {
  259.     if (sc_wait(har, ICR_REQUEST) == 0) {
  260.         return (-1);
  261.     }
  262.     if ((har->icr & ICR_BITS) != bits) {
  263.         if (bits != ICR_STATUS) sc_error(seqerr_msg);    /* Hack hack */
  264.         return (-1);
  265.     }
  266.     return (har->cmd_stat);
  267. }
  268.